// opt: 0
// flag: -g
//
// bzoj3926
// 题意：给定一个叶子树不超过20的树，树上每个节点有颜色，颜色类型不超过10,
//       树上两个节点确定一条路径，得到颜色序列，正反算两总，求有多少不同
//       颜色序列。
//
// 题解：反过来从每个叶子结点dfs建立一个大trie，然后由这个大trie建立广义
//       后缀自动机（多个串的自动机），然后就是在自动机上求不同子串个数，
//       这是经典应用，用dp球从初始节点出发到所有节点不同路径数就行。
//
// run: $exec < input
// opt: 0
//
#include <cstdio>

int const alpha_size = 10;
int const maxn = 100007;

struct state
{
	int len;
	state * link, * child[alpha_size];
} sam_state[maxn * 44], * sam_head;

int sam_alloc = 1;

struct trie
{
	trie * child[alpha_size];
} trie_node[maxn * 22], * trie_head;

int trie_alloc = 1;

int next[2 * maxn], end_point[2 * maxn], head[maxn];
int alloc = 1;
int color[maxn], degree[maxn];
bool vis[maxn];
int n, m;

void add_edge(int u, int v)
{
	end_point[alloc] = v; next[alloc] = head[u]; head[u] = alloc++;
	end_point[alloc] = u; next[alloc] = head[v]; head[v] = alloc++;
	degree[u]++;  degree[v]++;
}

trie * trie_node_alloc()
{
	trie * tmp = trie_node + trie_alloc++;
	return tmp;
}

void build_trie(trie * now, int u)
{
	if (!now->child[color[u]])
		now->child[color[u]] = trie_node_alloc();
	now = now->child[color[u]];
	vis[u] = true;
	for (int p = head[u]; p; p = next[p])
		if (!vis[end_point[p]])
			build_trie(now, end_point[p]);
	vis[u] = false;
}

state * sam_state_alloc()
{
	state * tmp = sam_state + sam_alloc++;
	return tmp;
}

state * sam_extend(state * last, int x) // x [0, alpha_sie) here is m
{
	state * cur = sam_state_alloc();
	cur->len = last->len + 1;
	state * p;
	for (p = last; p && !p->child[x]; p = p->link)
		p->child[x] = cur;
	if (!p) cur->link = sam_head;
	else {
		state * q = p->child[x];
		if (p->len + 1 == q->len)
			cur->link = q;
		else {
			state * clone = sam_state_alloc();
			// clone
			*clone = *q;
			clone->len = p->len + 1;

			for (; p && p->child[x] == q; p = p->link)
				p->child[x] = clone;
			q->link = cur->link = clone;
		}
	}
	return cur;
}

void build_sam(state * now, trie * t)
{
	for (int i = 0; i < m; i++)
		if (t->child[i]) {
			state * tmp = sam_extend(now, i);
			build_sam(tmp, t->child[i]);
		}
}

long long path_count[44 * maxn];

long long number_of_different_substring(int s)
{
	if (path_count[s]) return path_count[s];
	state * ts = sam_state + s;
	long long count = 1;
	for (int i = 0; i < m; i++)
		if (ts->child[i])
			count += number_of_different_substring(ts->child[i] - sam_state);
	return path_count[s] = count;
}

int main()
{
	std::scanf("%d %d", &n, &m);
	for (int i = 0; i < n; i++) std::scanf("%d", &color[i]);
	for (int i = 1, x, y; i < n; i++) {
		std::scanf("%d %d", &x, &y);
		add_edge(--x, --y);
	}

	trie_head = trie_node_alloc();
	for (int i = 0; i < n; i++)
		if (degree[i] == 1) build_trie(trie_head, i);

	sam_head = sam_state_alloc();
	build_sam(sam_head, trie_head);
	std::printf("%lld\n", number_of_different_substring(sam_head - sam_state) - 1);
}

